import Draw from 'ol/interaction/Draw';
import { unByKey } from 'ol/Observable';
import Overlay from 'ol/Overlay';
import { getArea, getLength } from 'ol/sphere';
import { LineString, Polygon } from 'ol/geom';
import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style';
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';

function Measure(map) {
    this.map = map;
    this.meavector = null; // 测量图层
    this.overlays = []; // 存储所有 Overlay
    this.draw = null; //存储draw
    this.helpTooltip = null; //存储helpTooltip
}

/**
 * description 测量折线距离、多边形面积
 * @param measureType 测量的类型 polygon line
 */
Measure.prototype.measure = function (measureType) {
    // 创建图层或清除数据源
    if (!this.meavector) {
        let measource = new VectorSource({ wrapX: false });
        this.meavector = new VectorLayer({
            name: '测量图层',
            source: measource,
            zIndex: 11,
            declutter: false
        });
        this.map.addLayer(this.meavector);
    } else {
        // 清除数据
        this.meavector.getSource().clear();

        // 清除所有 Overlay
        this.removeAllOverlays();
    }
    const self = this;

    /**
     * 当前绘制的功能
     * @type {module:ol/Feature~Feature}
     */
    let sketch;

    let helpTooltipElement;

    let measureTooltipElement;
    let measureTooltip;

    let continuePolygonMsg = '继续点击绘制多边形';
    let continueLineMsg = '继续点击绘制线';

    createMeasureTooltip();
    createHelpTooltip();

    /**
     * 监测绘制点移动
     * @param {module:ol/MapBrowserEvent~MapBrowserEvent} evt The event.
     */
    let pointerMoveHandler = function (evt) {
        if (evt.dragging) {
            return;
        }
        /** @type {string} */
        let helpMsg = '请点击开始绘制';

        if (sketch) {
            let geom = sketch.getGeometry();
            if (geom instanceof Polygon) {
                helpMsg = continuePolygonMsg;
            } else if (geom instanceof LineString) {
                helpMsg = continueLineMsg;
            }
        }

        helpTooltipElement.innerHTML = helpMsg;
        self.helpTooltip.setPosition(evt.coordinate);

        helpTooltipElement.classList.remove('hidden');
    };

    this.map.on('pointermove', pointerMoveHandler);

    this.map.getViewport().addEventListener('mouseout', function () {
        helpTooltipElement.classList.add('hidden');
    });

    let formatLength = function (line) {
        let sourceProj = 'EPSG:4326';
        let length = getLength(line, {
            radius: 6378137,
            projection: sourceProj
        });
        let output;
        if (length > 100) {
            output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km';
        } else {
            output = Math.round(length * 100) / 100 + ' ' + 'm';
        }
        return output;
    };
    let formatArea = function (polygon) {
        let sourceProj = 'EPSG:4326';
        let area = getArea(polygon, {
            radius: 6378137,
            projection: sourceProj
        });
        let output;
        if (area > 10000) {
            output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>';
        } else {
            output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>';
        }
        return output;
    };

    let source = this.meavector.getSource();

    function addInteraction() {
        let type = measureType == 'area' ? 'Polygon' : 'LineString';
        self.draw = new Draw({
            source: source,
            type: type,
            style: new Style({
                fill: new Fill({
                    color: 'rgba(255, 255, 255, 0.2)'
                }),
                stroke: new Stroke({
                    color: 'rgba(0, 0, 0, 0.5)',
                    lineDash: [10, 10],
                    width: 2
                }),
                image: new CircleStyle({
                    radius: 5,
                    stroke: new Stroke({
                        color: 'rgba(0, 0, 0, 0.7)'
                    }),
                    fill: new Fill({
                        color: 'rgba(255, 255, 255, 0.2)'
                    })
                })
            })
        });
        self.map.addInteraction(self.draw);

        let listener;
        self.draw.on(
            'drawstart',
            function (evt) {
                // 设置 sketch
                sketch = evt.feature;

                /** @type {module:ol/coordinate~Coordinate|undefined} */
                let tooltipCoord = evt.coordinate;

                listener = sketch.getGeometry().on('change', function (evt) {
                    let geom = evt.target;
                    let output;
                    if (geom instanceof Polygon) {
                        output = formatArea(geom);
                        tooltipCoord = geom.getInteriorPoint().getCoordinates();
                    } else if (geom instanceof LineString) {
                        output = formatLength(geom);
                        tooltipCoord = geom.getLastCoordinate();
                    }
                    measureTooltipElement.innerHTML = output;
                    measureTooltip.setPosition(tooltipCoord);
                });
            },
            this
        );

        self.draw.on(
            'drawend',
            function () {
                measureTooltipElement.className = 'tooltip tooltip-static';
                measureTooltip.setOffset([0, -7]);
                // 重置 sketch
                sketch = null;
                // 重置测量文本标签
                measureTooltipElement = null;
                createMeasureTooltip();

                unByKey(listener);
                self.map.un('pointermove', pointerMoveHandler);

                self.map.removeInteraction(self.draw);
                helpTooltipElement.classList.add('hidden');
                // 移除帮助提示框
                if (self.helpTooltip) {
                    self.map.removeOverlay(self.helpTooltip);
                    self.helpTooltip = null;
                }
            },
            this
        );
    }

    function createHelpTooltip() {
        if (helpTooltipElement) {
            helpTooltipElement.parentNode.removeChild(helpTooltipElement);
        }
        helpTooltipElement = document.createElement('div');
        helpTooltipElement.className = 'tooltip hidden';
        self.helpTooltip = new Overlay({
            element: helpTooltipElement,
            offset: [15, 0],
            positioning: 'center-left'
        });
        self.map.addOverlay(self.helpTooltip);
        self.overlays.push(self.helpTooltip);
    }

    function createMeasureTooltip() {
        if (measureTooltipElement) {
            measureTooltipElement.parentNode.removeChild(measureTooltipElement);
        }
        measureTooltipElement = document.createElement('div');
        measureTooltipElement.className = 'tooltip tooltip-measure';
        measureTooltip = new Overlay({
            element: measureTooltipElement,
            offset: [0, -15],
            positioning: 'bottom-center'
        });
        self.map.addOverlay(measureTooltip);
        self.overlays.push(measureTooltip);
    }
    // 量测调用
    addInteraction();
};

/**
 * description 清除地图测量矢量
 */
Measure.prototype.clear = function () {
    if (this.meavector) {
        this.meavector.getSource().clear();
    }
    this.removeAllOverlays();
};

/**
 * description 清除所有Overlay
 */
Measure.prototype.removeAllOverlays = function () {
    this.overlays.forEach((overlay) => {
        this.map.removeOverlay(overlay);
    });
    this.overlays = [];
};

export default Measure;
